package org.xm.moretriggercommands.Event;

import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.xm.moretriggercommands.Main;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class RegionListener implements Listener {
    private final Map<String, Region> regions = new HashMap<>();
    private final Map<Player, String> currentRegions = new HashMap<>();

    public RegionListener() {
        loadRegions();
    }

    private void loadRegions() {

        List<String> regionIds = Main.getInstance().getConfig().getStringList("JoinRegion.Region");
        for (String id : regionIds) {
            String path = id + ".";
            Region region = new Region(
                    Main.getInstance().getConfig().getString(path + "RegionName"),
                    Main.getInstance().getConfig().getString(path + "RegionWorld"),
                    Main.getInstance().getConfig().getInt(path + "corner1.x"),
                    Main.getInstance().getConfig().getInt(path + "corner1.z"),
                    Main.getInstance().getConfig().getInt(path + "corner2.x"),
                    Main.getInstance().getConfig().getInt(path + "corner2.z"),
                    Main.getInstance().getConfig().getStringList(path + "Join-Command"),
                    Main.getInstance().getConfig().getStringList(path + "Exit-Command")
            );
            regions.put(id, region);
        }
    }

    @EventHandler
    public void onPlayerMove(PlayerMoveEvent event) {
        if (Main.getInstance().getConfig().getBoolean("JoinRegion.Switch", false)) {

            Player player = event.getPlayer();
            Location to = event.getTo();
            Location from = event.getFrom();

            // 检测玩家是否离开了某个区域
            if (currentRegions.containsKey(player) && !isInAnyRegion(to)) {
                Region leftRegion = regions.get(currentRegions.get(player));
                executeCommands(player, leftRegion.getExitCommands(), leftRegion.getName());
                currentRegions.remove(player);
            }

            // 检测玩家是否进入了某个区域
            for (Map.Entry<String, Region> entry : regions.entrySet()) {
                Region region = entry.getValue();
                if (!isSameBlockLocation(to, from) && region.isInRegion(to)) {
                    if (!entry.getKey().equals(currentRegions.get(player))) {
                        executeCommands(player, region.getJoinCommands(), region.getName());
                        currentRegions.put(player, entry.getKey());
                    }
                    return;
                }
            }
        }
    }

    @EventHandler
    public void onPlayerTeleport(PlayerTeleportEvent event) {
        if (Main.getInstance().getConfig().getBoolean("JoinRegion.Switch", false)) {

            Player player = event.getPlayer();
            Location to = event.getTo();
            Location from = event.getFrom();

            // 检测玩家是否离开了某个区域
            if (currentRegions.containsKey(player) && !isInAnyRegion(to)) {
                Region leftRegion = regions.get(currentRegions.get(player));
                executeCommands(player, leftRegion.getExitCommands(), leftRegion.getName());
                currentRegions.remove(player);
            }

            // 检测玩家是否进入了某个区域
            for (Map.Entry<String, Region> entry : regions.entrySet()) {
                Region region = entry.getValue();
                if (region.isInRegion(to)) {
                    if (!entry.getKey().equals(currentRegions.get(player))) {
                        executeCommands(player, region.getJoinCommands(), region.getName());
                        currentRegions.put(player, entry.getKey());
                    }
                    return;
                }
            }
        }
    }

    @EventHandler
    public void onPlayerJoin(PlayerJoinEvent event) {
        if (Main.getInstance().getConfig().getBoolean("JoinRegion.Switch", false)) {

            Player player = event.getPlayer();
            Location location = player.getLocation();

            // 检测玩家是否在某个区域内
            for (Map.Entry<String, Region> entry : regions.entrySet()) {
                Region region = entry.getValue();
                if (region.isInRegion(location)) {
                    // 如果在区域内，执行进入指令
                    executeCommands(player, region.getJoinCommands(), region.getName());
                    currentRegions.put(player, entry.getKey());
                    return;
                }
            }
        }
    }

    @EventHandler
    public void onPlayerQuit(PlayerQuitEvent event) {
        if (Main.getInstance().getConfig().getBoolean("JoinRegion.Switch", false)) {

            Player player = event.getPlayer();
            if (currentRegions.containsKey(player)) {
                // 清理玩家的区域状态
                currentRegions.remove(player);
            }
        }
    }

    private boolean isInAnyRegion(Location loc) {
        return regions.values().stream().anyMatch(region -> region.isInRegion(loc));
    }

    private void executeCommands(Player player, List<String> commands, String regionName) {
        for (String cmd : commands) {
            cmd = cmd.replace("%player_name%", player.getName())
                    .replace("%region_name%", regionName)
                    .replace("&", "§");
            Bukkit.dispatchCommand(Bukkit.getConsoleSender(), cmd);
        }
    }

    private boolean isSameBlockLocation(Location loc1, Location loc2) {
        return loc1.getBlockX() == loc2.getBlockX() &&
                loc1.getBlockZ() == loc2.getBlockZ() &&
                loc1.getWorld().getName().equals(loc2.getWorld().getName());
    }

    private static class Region {
        private final String name;
        private final String world;
        private final int minX;
        private final int maxX;
        private final int minZ;
        private final int maxZ;
        private final List<String> joinCommands;
        private final List<String> exitCommands;

        public Region(String name, String world, int x1, int z1, int x2, int z2,
                      List<String> joinCommands, List<String> exitCommands) {
            this.name = name;
            this.world = world;
            this.minX = Math.min(x1, x2);
            this.maxX = Math.max(x1, x2);
            this.minZ = Math.min(z1, z2);
            this.maxZ = Math.max(z1, z2);
            this.joinCommands = joinCommands;
            this.exitCommands = exitCommands;
        }

        public boolean isInRegion(Location loc) {
            if (!loc.getWorld().getName().equals(world)) return false;
            int x = loc.getBlockX();
            int z = loc.getBlockZ();
            return x >= minX && x <= maxX && z >= minZ && z <= maxZ;
        }

        public String getName() { return name; }
        public List<String> getJoinCommands() { return joinCommands; }
        public List<String> getExitCommands() { return exitCommands; }
    }
}